// 调试管理器

import { BaseManager } from '../core/BaseManager';
import { RedisClient } from '../core/RedisClient';
import { KeyGenerator } from '../utils/keyGenerator';

export interface DebugInfo {
  timestamp: Date;
  operation: string;
  key?: string | undefined;
  value?: any;
  result?: any;
  error?: string | undefined;
  executionTime: number;
}

export interface DebugStats {
  totalOperations: number;
  successfulOperations: number;
  failedOperations: number;
  averageExecutionTime: number;
  operationTypes: Record<string, number>;
}

export class DebugManager extends BaseManager {
  private debugLogs: DebugInfo[] = [];
  private maxLogSize: number = 1000;
  private isEnabled: boolean = false;

  constructor(client: RedisClient) {
    super(client, new KeyGenerator({ prefix: 'debug' }));
  }

  /**
   * 启用调试模式
   */
  enable(): void {
    this.isEnabled = true;
    this.logger.info('Debug mode enabled');
  }

  /**
   * 禁用调试模式
   */
  disable(): void {
    this.isEnabled = false;
    this.logger.info('Debug mode disabled');
  }

  /**
   * 检查是否启用调试模式
   */
  isDebugEnabled(): boolean {
    return this.isEnabled;
  }

  /**
   * 记录调试信息
   */
  log(
    operation: string,
    key?: string,
    value?: any,
    result?: any,
    error?: string,
    executionTime?: number
  ): void {
    if (!this.isEnabled) return;

    const debugInfo: DebugInfo = {
      timestamp: new Date(),
      operation,
      key,
      value: this.sanitizeValue(value),
      result: this.sanitizeValue(result),
      error,
      executionTime: executionTime ?? 0,
    };

    this.debugLogs.push(debugInfo);

    // 限制日志大小
    if (this.debugLogs.length > this.maxLogSize) {
      this.debugLogs = this.debugLogs.slice(-Math.floor(this.maxLogSize * 0.8));
    }

    // 输出到控制台（如果需要）
    if (error) {
      this.logger.error(`DEBUG [${operation}] ${key ?? ''}: ${error}`, {
        value: debugInfo.value,
        executionTime,
      });
    } else {
      this.logger.debug(`DEBUG [${operation}] ${key ?? ''}: Success`, {
        result: debugInfo.result,
        executionTime,
      });
    }
  }

  /**
   * 获取调试日志
   */
  getLogs(limit?: number): DebugInfo[] {
    const logs = this.debugLogs.slice();
    return limit ? logs.slice(-limit) : logs;
  }

  /**
   * 获取特定操作的日志
   */
  getLogsByOperation(operation: string, limit?: number): DebugInfo[] {
    const filtered = this.debugLogs.filter(log => log.operation === operation);
    return limit ? filtered.slice(-limit) : filtered;
  }

  /**
   * 获取特定键的日志
   */
  getLogsByKey(key: string, limit?: number): DebugInfo[] {
    const filtered = this.debugLogs.filter(log => log.key === key);
    return limit ? filtered.slice(-limit) : filtered;
  }

  /**
   * 获取错误日志
   */
  getErrorLogs(limit?: number): DebugInfo[] {
    const filtered = this.debugLogs.filter(log => log.error);
    return limit ? filtered.slice(-limit) : filtered;
  }

  /**
   * 获取调试统计信息
   */
  getStats(): DebugStats {
    const totalOperations = this.debugLogs.length;
    const successfulOperations = this.debugLogs.filter(log => !log.error).length;
    const failedOperations = totalOperations - successfulOperations;

    const totalExecutionTime = this.debugLogs.reduce((sum, log) => sum + log.executionTime, 0);
    const averageExecutionTime = totalOperations > 0 ? totalExecutionTime / totalOperations : 0;

    const operationTypes: Record<string, number> = {};
    for (const log of this.debugLogs) {
      operationTypes[log.operation] = (operationTypes[log.operation] ?? 0) + 1;
    }

    return {
      totalOperations,
      successfulOperations,
      failedOperations,
      averageExecutionTime,
      operationTypes,
    };
  }

  /**
   * 清空调试日志
   */
  clearLogs(): void {
    this.debugLogs = [];
    this.logger.info('Debug logs cleared');
  }

  /**
   * 设置最大日志大小
   */
  setMaxLogSize(size: number): void {
    if (size <= 0) {
      throw new Error('Max log size must be greater than 0');
    }
    this.maxLogSize = size;
  }

  /**
   * 获取最大日志大小
   */
  getMaxLogSize(): number {
    return this.maxLogSize;
  }

  /**
   * 导出调试日志为JSON
   */
  exportLogs(): string {
    return JSON.stringify(
      {
        exportedAt: new Date(),
        totalLogs: this.debugLogs.length,
        stats: this.getStats(),
        logs: this.debugLogs,
      },
      null,
      2
    );
  }

  /**
   * 分析性能瓶颈
   */
  analyzePerformance(): {
    slowestOperations: DebugInfo[];
    operationPerformance: Record<string, { count: number; avgTime: number; maxTime: number }>;
    recommendations: string[];
  } {
    const slowestOperations = this.debugLogs
      .filter(log => !log.error)
      .sort((a, b) => b.executionTime - a.executionTime)
      .slice(0, 10);

    const operationPerformance: Record<
      string,
      { count: number; avgTime: number; maxTime: number }
    > = {};

    for (const log of this.debugLogs) {
      if (log.error) continue;

      if (!operationPerformance[log.operation]) {
        operationPerformance[log.operation] = { count: 0, avgTime: 0, maxTime: 0 };
      }

      const perf = operationPerformance[log.operation]!;
      perf.count++;
      perf.avgTime = (perf.avgTime * (perf.count - 1) + log.executionTime) / perf.count;
      perf.maxTime = Math.max(perf.maxTime, log.executionTime);
    }

    const recommendations: string[] = [];

    // 分析并提供建议
    for (const [operation, perf] of Object.entries(operationPerformance)) {
      if (perf.avgTime > 100) {
        recommendations.push(
          `${operation} 操作平均耗时较长 (${perf.avgTime.toFixed(2)}ms)，考虑优化`
        );
      }
      if (perf.maxTime > 1000) {
        recommendations.push(
          `${operation} 操作最大耗时过长 (${perf.maxTime.toFixed(2)}ms)，需要调查`
        );
      }
    }

    const errorRate = this.debugLogs.filter(log => log.error).length / this.debugLogs.length;
    if (errorRate > 0.05) {
      recommendations.push(`错误率较高 (${(errorRate * 100).toFixed(1)}%)，需要检查错误原因`);
    }

    return {
      slowestOperations,
      operationPerformance,
      recommendations,
    };
  }

  /**
   * 清理敏感数据
   */
  private sanitizeValue(value: any): any {
    if (value === null || value === undefined) {
      return value;
    }

    if (typeof value === 'string') {
      // 限制字符串长度
      return value.length > 100 ? value.substring(0, 100) + '...' : value;
    }

    if (typeof value === 'object') {
      // 限制对象大小
      const str = JSON.stringify(value);
      return str.length > 200 ? str.substring(0, 200) + '...' : value;
    }

    return value;
  }
}
